import { IDispose } from "./IGameManager";

/**
 * VM 主接口
 * TIPS:已实现 beforeCreate ,created, mounted,watch-监听器（可以动态改变值）
 * TODO:尚未实现销毁生命周期（beforeDestroy,destroyed），数据修改监听(beforeUpdate,updated)
 */
export interface IVMMain {
  /**
   * 配置参数
   * {
   *   el:元素
   *   data:数据
   *   beforeCreate:function(){},
   *   created:function(){},
   *   methods:绑定函数
   *   watch:数据监听器（数组类型监听器参数：newval,old,node,index）
   * }
   */
  $options: any;
  /**是否销毁状态 */
  $isDestroy: boolean;
  //数据挂载后代理参数
  $pools: Array<IDispose>; //资源池
  /**渲染元素 */
  $el: any;

  /**当前VM标识 */
  $identity: number;
  /**命令解析器 */
  $icompile: ICompile;
  /**当前监听器 */
  $targetWatcher: IWatcher;

  /**
   * 设置特殊数据-如列表数据的更新渲染到视图
   * @param target 特殊值（数据列表）
   * @param key (数据列表-填写索引）
   * @param val 新值
   */
  $set(target, key, val);
  /**销毁VM */
  $destroy();
}
/**
 * VM 指令解析接口
 */
export interface ICompile {
  /**
   *   对元素进行节点遍历解析
   * @param el 解析元素
   * @param data 解析数据，for循环时有用
   */
  compileElement(el, data?);
  // 文档碎片，遍历过程中会有多次的dom操作，为提高性能我们会将el节点转化为fragment文档碎片进行解析操作
  // 解析操作完成，将其添加回真实dom节点中
  /**
   * 文档碎片，为提高性能，再内存操作dom完毕后加入节点，
   * @param el 操作元素
   */
  nodeFragment(el);
  /**
   * 指令解析
   * @param node 解析节点
   * @param data 解析数据-for 循环时指定item数据绑定
   */
  compile(node, data?);
}

/**
 * VM 数据劫持接口
 */
export interface IObserve {
  /**
   * 数据循环 遍历,
   * @param obj 数据对象
   */
  walk(obj: object);
  /**
   * 拦截数据
   */
  observeArray(items);
}

/**订阅器 接口*/
export interface ISubscriber {
  /**
   * 添加订阅
   * @param sub 订阅者
   */
  add(sub: IWatcher);
  /**
   * 移除订阅
   * @param sub 订阅者
   */
  remove(sub: IWatcher);
  /**
   * 数据变更通知
   */
  notify();
  /**
   * 添加依赖监听
   */
  depend();
}
/**
 * 数据监听 接口
 */
export interface IWatcher {
  /**
   * 数据更新
   */
  update();
  /**
   *绑定视图更新数据
   */
  run();
  /**
   * 获取数据
   */
  get();
  /**
   * 添加订阅对象
   * @param sub 订阅者
   */
  addSub(sub: ISubscriber);
}
export interface IVMUtil {
  /**
   * 定义值监听函数
   */
  Define(obj, key, val, enumerable?);
  /**
   *  是否包含指定键值
   */
  hasOwn(obj, key);
  /**
   * 移除数据
   */
  delData(target, key);
}
/**
 * VM 控制组件
 */
export interface IVMComponent {
  /**
   * VM 数据绑定内容 (绑定数据由逗号分割)
   * 格式一：属性绑定 v-attr=name
   * 格式二：函数绑定 v-on:click=funcName
   * 格式三：模型绑定 v-model 数据双向绑定
   */
  VContent: string;
  /**
   * 实现文本属性绑定 v-text
   */
  VText: string;
  /**
   * 实现模型属性绑定 v-model
   */
  VModel: string;
  /**
   * 实现for 循环、  v-for
   * 语法 item in data.list
   */
  VFor: string;
  /**
   * 是否显示
   */
  VDisplay: string;
  /**
   * 实现模型属性绑定 v-on:click=funcName
   * 需要自定义实现 冒号部分 (:click=funcName)
   */
  VBind: string;
}
/**
 * 组件指令判断
 */
export interface IComponentDirective {
  /**
   * 是否组件
   * @param el 操作元素
   */
  isComponent(el);
  /**
   * 获取元素VM组件
   * @param el 操作元素
   */
  getComponent(el);
  /**
   * 获取元素 子元素
   * @param el 操作元素
   */
  getChildNodes(el);
  /**
   * 添加监听事件
   *  @param el 执行元素
   * @param eventType 事件名称
   * @param func 执行函数
   * @param once 执行次数 0 代表一直执行
   */
  addEventListener(el: any, eventType: string, func: any, once: number);
  /**
   * 添加输入框监听事件
   *  @param el 执行元素
   * @param eventType 事件名称
   * @param func 执行函数
   * @param once 执行次数 0 代表一直执行
   */
  addInputListener(el: any, func: any);
}
/**渲染工具类 */
export interface IRenderUtil {
  $elm: any; //当前渲染对象

  textUpdater(node, value);
  classUpdater();
  modelUpdater(node, value, oldValue);
}
/**MVVM参数接口 */
export interface IVMOptions {
  /**解析元素 */
  el: any;
  /**绑定数据模型 */
  data: any;
  /**计算属性 */
  computed?: any;
  /*数据监听，数据变化时可以对数据进行新旧值监听，且可以通关return 返回新的值 */
  watch?: any;
  /**事件监听-参数点击按钮 e */
  methods?: any;
  /**动画函数 */
  actions?: any;
  /**自定义组件-组件操作中转 */
  control?: any;
  /**系统组件 */
  components?: any;

  /**同步初始化函数-初始化时需要同步处理操作执行函数  参数： el, data,init(初始化完毕执行函数)   */
  syncInit?: Function;
  /**数据初始化前处理函数，可以给data赋值值,无法操作系统组件及控件
   * 参数： el, data */
  beforeCreate?: Function;
  /**初始化完毕、数据劫持完毕 参数： el, data */
  created?: Function;
  /**数据解析完毕 参数： el, data*/
  mounted?: Function;
  /**销毁前 参数： el, data*/
  beforeDestroy?: Function;
  /**销毁后 参数： el, data*/
  destroyed?: Function;
}
